import { Fsm } from "./Fsm";
import { FsmBase } from "./FsmBase";
import { IFsm } from "./IFsm";
import { IFsmState } from "./IFsmState";

/**
 * 有限状态机管理器
 */
class FsmManager{
    private static created:boolean = false;
    constructor(){
        if(FsmManager.created){
            throw new Error("FsmManager is singleton!");
        }
        FsmManager.created = true;
        this._fsms = new Map();
    }

    private _fsms:Map<string, FsmBase>;

    /**
     * 获取有限状态机数量
     */
    get count():number{
        return this._fsms.size;
    }

    /**
     * 是否存在有限状态机
     * @param name 有限状态机名称
     * @returns 
     */
    hasFsm(name:string):boolean{
        return this._fsms.has(name);
    }

    /**
     * 根据名称获取有限状态机
     * @param name 有限状态机名称
     * @returns 
     */
    getFsm<T extends FsmBase>(name:string):T{
        return this._fsms.get(name) as T;
    }

    /**
     * 获取所有存在的Fsm
     * @returns 
     */
    getAllFsms():FsmBase[]{
        return Array.from(this._fsms.values());
    }

    /**
     * 创建一个有限状态机
     * @param owner 有限状态机拥有者
     * @param states 状态列表
     * @param name 有限状态机名称,默认:default
     * @returns 
     */
    createFsm<OwnerT, DataT>(owner:OwnerT, states:IFsmState<OwnerT, DataT>[], name:string="default", data?:DataT):IFsm<OwnerT, DataT>{
        if(this.hasFsm(name)){
            throw new Error(`Already exist FSM:${name}`);
        }

        let fsm:Fsm<OwnerT, DataT> = Fsm.create<OwnerT, DataT>(name, owner, states, data);
        this._fsms.set(name, fsm);
        return fsm;
    }

    /**
     * 销毁有限状态机
     * @param fsmName 
     * @returns 
     */
    destroyFsmByName(fsmName:string):boolean{
        let fsm:FsmBase = this.getFsm(fsmName);
        if(fsm){
            fsm.shutdown();
            this._fsms.delete(fsmName);
            return true;
        }
        return false;
    }

    /**
     * 销毁有限状态机
     * @param fsm 状态机 
     * @returns 
     */
    destroyFsm(fsm:FsmBase):boolean{
        let result = this._fsms.delete(fsm.name);
        fsm.shutdown();
        return result;
    }

    /**
     * 销毁有限状态机
     * @param owner 有限状态机持有者
     * @returns 
     */
    destroyFsmByOwner(owner:any):boolean{
        let keys = this._fsms.keys();
        let key = keys.next();
        while(!key.done){
            let fsm = this._fsms.get(key.value);
            if(fsm?.ownerType == owner.constructor.name){
                fsm!.shutdown();
                this._fsms.delete(key.value);
                return true;
            }
            key = keys.next();
        }
        return false;
    }

    /**
     * 关闭并清理有限状态机管理器
     */
    public shutdown():void{
        this._fsms.forEach((fsm, key)=>{
            fsm.shutdown();
        });

        this._fsms.clear();
    }
}

/**
 * 有限状态机管理器
 */
export var fsmManager:FsmManager = new FsmManager();
